/*
 * Copyright Owen Watson 2009
 * 
 * This file is part of ArtNotes.
 *
 * ArtNotes is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * ArtNotes is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with ArtNotes.  If not, see <http://www.gnu.org/licenses/>.
*/
				
using System;
using System.Collections.Generic;
using System.Linq;
using SQLite;

namespace ArtNotes
{
	/// <summary>
	/// This provides an implementation for accessing
	/// the artnotes database, allowing the ease of
	/// creating / updating / deleting / listing
	/// the various items, such as Tags and Images.
	/// 
	/// This really needs to be moved to using System.Data
	/// </summary>
	public class ANDatabase : SQLiteConnection
	{
		public ANDatabase (string path) : base(path)
		{
		}
		
		public IEnumerable<Tag> ListAllTags ()
		{
			return Query<Tag> ("select distinct TagName from Tag order by TagName");
		}
		
		public IEnumerable<Image> ListAllImages ()
		{
			return Query<Image> ("select * from Image order by Id");
		}
		
		public IEnumerable<Tag> ListTagsForImage (Image image)
		{
			return Query<Tag> ("select * from Tag where ImageId = ?", image.Id);
		}
		
		public IEnumerable<Image> ListImagesForTag (Tag tag)
		{
			return Query<Image> ("select * from Image where Id in (select ImageID from Tag where TagName = ?)", tag.TagName);
		}
		
		public FlickrImage GetFlickrImageForImage (Image image)
		{
			return Query<FlickrImage> ("select * from FlickrImage where ImageID = ?", image.Id).FirstOrDefault ();
		}
		
		public AppInfo GetAppInfo()
		{
			return Query<AppInfo>("select * from AppInfo").FirstOrDefault();
		}
		
		public Image GetImageByID (int id)
		{
			return Query<Image> ("select * from Image where Id = ?", id).FirstOrDefault ();
		}
		
		public Tag GetTagByID (int id)
		{
			return Query<Tag> ("select * from Tag where Id = ?", id).FirstOrDefault ();
		}
		
		public Tag GetTagByName (string tagName)
		{
			return Query<Tag> ("select * from Tag where TagName = ?", tagName).FirstOrDefault ();
		}
		
		public bool UpdateTagsForImage (Image image, Tag[] newTags)
		{
			try
			{
				bool tagFound = false;
				
				if(newTags.Length ==0)
				{
					Console.WriteLine("no tags!");
					// probably shouldn't do this...
					newTags = new Tag[1];
					newTags[0] = new Tag() { TagName = "Unsorted", ImageID = image.Id};
					Console.WriteLine("Added \"Unsorted\"");
				}
				
				Tag[] oldTags = this.ListTagsForImage (image).ToArray ();
				
				for (int i = 0; i < oldTags.Length; i++)
				{
					tagFound = false;
					for (int j = 0; j < newTags.Length; j++)
					{
						if (newTags[j].TagName.Equals (oldTags[i].TagName))
						{
							Console.WriteLine ("Found Existing Tag : " + oldTags[i].TagName);
							tagFound = true;
							break;
						}
					}
					if (!tagFound)
					{
						Console.WriteLine ("Removing Tag : " + oldTags[i].TagName);
						this.RemoveTag (oldTags[i]);
					}
				}
				
				tagFound = false;
				
				for (int i = 0; i < newTags.Length; i++)
				{
					tagFound = false;
					for (int j = 0; j < oldTags.Length; j++)
					{
						if (oldTags[j].TagName.Equals (newTags[i].TagName))
						{
							Console.WriteLine ("Found Existing Tag : " + newTags[i].TagName);
							tagFound = true;
							break;
						}
					}
					if (!tagFound)
					{
						Console.WriteLine ("Adding New Tag : " + newTags[i].TagName);
						this.CreateTag(new Tag(){TagName = newTags[i].TagName, ImageID = image.Id});
					}
				}
				return true;
			}
			catch (Exception e)
			{
				Console.WriteLine("Exception!");
				return false;
			}
		}
		
		public bool RemoveTag (Tag tag)
		{
			try
			{
				this.Execute ("delete from Tag where Id = ?", tag.Id);
				return true;
			}
			catch (Exception e)
			{
				Console.WriteLine("exception removing tag");
				return false;
			}
		}
		
		public bool RemoveImage (Image image)
		{
			try
			{
				this.Execute ("delete from Tag where ImageId = ?", image.Id);
				this.Execute ("delete from Image where Id = ?", image.Id);
				return true;
			}
			catch (Exception e)
			{
				return false;
			}
		}
		
		public void CreateAppInfo (AppInfo appInfo)
		{
			try
			{
				this.Insert (appInfo);
			}
			catch (Exception e)
			{
				Console.WriteLine("exception creating AppInfo : " + e.Message);
				//return null;
			}
		}
		
		public void CreateTag (Tag tag)
		{
			try
			{
				this.Insert (tag);
			}
			catch (Exception e)
			{
				Console.WriteLine("exception creating tag : " + e.Message);
				//return null;
			}
		}
		
		public Image CreateImage (Image image)
		{
			try
			{
				Image img = this.Insert (image);
				this.Insert (
						new Tag ()
						{
							TagName = "Unsorted",
							ImageID = img.Id						
						}
					);
				return img;
			}
			catch (Exception e)
			{
				// ...should check to make sure the 'image' hasn't been created...
				return null;
			}
		}
		
		public bool CreateImage (Image image, Tag[] tags)
		{
			try {
				Image img = this.Insert (image);
				for (int i = 0; i < tags.Length; i++)
				{
					this.Insert (
					    new Tag()
					    {
							TagName = tags[i].TagName,
							ImageID = img.Id
						}
					);
				}
				if ((tags.Length == 0) || (tags.Equals(null)))
					this.Insert (
						new Tag ()
						{
							TagName = "Unsorted",
							ImageID = img.Id						
						}
					);
				return true;
			}
			catch (Exception e)
			{
				// ...should check to make sure the 'image' hasn't been created...
				// ...should also check each tag...
				return false;
			}
		}
	}
}
